package com.vxdata.utils.modules.逆向工程.swagge接口转md;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.vxdata.common.utils.StringUtils;
import com.vxdata.utils.modules.逆向工程.swagge接口转md.vo.ColInfoVo;
import com.vxdata.utils.modules.逆向工程.swagge接口转md.vo.SwaggerVo;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.stream.Collectors;


// 在线md转word https://products.groupdocs.app/zh/conversion/md-to-docx
public class swagger接口文档转md格式 {

    public static void main(String[] args) throws IOException {
        // 获取swagger.json文件内容
        swagger接口文档转md格式 swa = new swagger接口文档转md格式();
        String swaggerFile = "\\swagger\\swagger.json";
        JSONObject swaggerJson = swa.readFileFromClasspath(swaggerFile);

        Map<String, List<ColInfoVo>> colMap = colMap(swaggerJson);


        List<SwaggerVo> swaggerVoList = getSwaggerVoList(swaggerJson, colMap);
        String mdStr = mdStr(swaggerVoList, colMap);
        System.out.println(mdStr);

//        colMap.forEach((k, v) -> {
//            System.out.println(JSON.toJSONString(v));
//        });

    }


    /**
     * 组装md 语句
     *
     * @param swaggerVoList
     * @return
     */
    public static String mdStr(List<SwaggerVo> swaggerVoList, Map<String, List<ColInfoVo>> colMap) {
        for (SwaggerVo vo : swaggerVoList) {
            String[] split = vo.getScene().substring(1).split("/");
            String s0 = split[0];
            vo.setS0(s0);
            if (split.length > 1) {
                String s1 = split[1];
                vo.setS1(s1);
            }
            if (split.length > 2) {
                vo.setS2(split[2]);
            }
            vo.setCj(split.length);
        }

        StringBuilder mdStr = new StringBuilder();


        Map<Integer, List<SwaggerVo>> cjMap = swaggerVoList.stream().collect(Collectors.groupingBy(SwaggerVo::getCj));

        cjMap.forEach((k, v) -> {
            // 只有一级
            if (k == 1) {
                Map<String, List<SwaggerVo>> s0Map = v.stream().collect(Collectors.groupingBy(SwaggerVo::getS0));
                s0Map.forEach((x, y) -> {
                    mdStr.append("# " + x + "\n");
                    mdStr.append(colStr(y, colMap));
                });
            }
            if (k == 2) {
                Map<String, List<SwaggerVo>> s0Map = v.stream().collect(Collectors.groupingBy(SwaggerVo::getS0));
                s0Map.forEach((x, y) -> {
                    mdStr.append("# " + x + "\n");
                    Map<String, List<SwaggerVo>> s1Map = y.stream().collect(Collectors.groupingBy(SwaggerVo::getS1));
                    s1Map.forEach((m, n) -> {
                        mdStr.append("## " + m + "\n");
                        mdStr.append(colStr(n, colMap));
                    });
                });
            }
            if (k == 3) {
                Map<String, List<SwaggerVo>> s0Map = v.stream().collect(Collectors.groupingBy(SwaggerVo::getS0));
                s0Map.forEach((x, y) -> {
                    mdStr.append("# " + x + "\n");
                    Map<String, List<SwaggerVo>> s1Map = y.stream().collect(Collectors.groupingBy(SwaggerVo::getS1));
                    s1Map.forEach((m, n) -> {
                        mdStr.append("## " + m + "\n");
                        Map<String, List<SwaggerVo>> s2Map = n.stream().collect(Collectors.groupingBy(SwaggerVo::getS2));
                        s2Map.forEach((p, q) -> {
                            mdStr.append("### " + p + "\n");
                            mdStr.append(colStr(q, colMap));
                        });
                    });
                });
            }
        });
        return mdStr.toString();
    }

    /**
     * 每个接口组装md 语句
     *
     * @param voList
     * @param colMap
     * @return
     */
    public static StringBuilder colStr(List<SwaggerVo> voList, Map<String, List<ColInfoVo>> colMap) {
        StringBuilder mdStr = new StringBuilder();

        for (SwaggerVo vo : voList) {
            mdStr.append("#### " + vo.getDescription() + "\n\n");
            mdStr.append("**业务场景:**     " + vo.getScene() + "\n\n");
            mdStr.append("**接口说明:**     " + vo.getDescription() + "\n\n");
            mdStr.append("**请求地址:**     " + vo.getPath() + "\n\n");
            mdStr.append("**请求方式:**     " + vo.getMethod() + "\n\n");
            mdStr.append("\n");

            // TODO 请求参数
            String paramName = StringUtils.isNotEmpty(vo.getParamName()) ? vo.getParamName() : "";
            mdStr.append("**请求参数:**     " + paramName + "\n\n");

            List<ColInfoVo> paramList = vo.getParamList();
            if (StringUtils.isNotEmpty(paramName)) {
                List<ColInfoVo> infoList = colMap.get(paramName);
                if (infoList != null) {
                    paramList.addAll(infoList);
                } else {
                    System.out.println("请求参数 找不到的对象: " + paramName);
                }
            }

            if (CollectionUtil.isNotEmpty(paramList) && paramList.size() > 0) {
                mdStr.append("| 参数名称 | 数据类型 | 参数说明 |\n");
                mdStr.append("| -------- | -------- | -------- |\n");
                paramList.forEach(p -> {
                    mdStr.append("|" + p.getColName() + "|" + p.getType() + "|" + p.getDescription() + "|\n");
                });
                mdStr.append("\n\n");

                mdStr.append("**请求示例:** \n\n");
                mdStr.append("~~~json\n");
                String shiLi = SwaggerResultListToShiLiJson.getShiLi(paramList);
                mdStr.append(shiLi + "\n");
                mdStr.append("~~~\n");
            }

            // TODO 返回结果

            String resultName = StringUtils.isNotEmpty(vo.getResultName()) ? vo.getResultName() : "";
            List<ColInfoVo> resultList = vo.getResultList();

            mdStr.append("**返回参数:**     " + resultName + "\n\n");
            if (StringUtils.isEmpty(resultName)) {
                continue;
            }
            mdStr.append("| 参数名称 | 数据类型 | 参数说明 |\n");
            mdStr.append("| -------- | -------- | -------- |\n");

            if (resultName.contains("R")) {
                List<ColInfoVo> R = colMap.get("R");
                resultList.addAll(R);

                String[] split = resultName.split("«");
                if (split.length == 2) {
                    String s1 = split[1].replace("»", "");
                    if (!s1.equals("string")) {
                        List<ColInfoVo> infoList = colMap.get(s1);
                        if (CollectionUtil.isNotEmpty(infoList)) {
                            infoList = JSON.parseArray(JSON.toJSONString(infoList), ColInfoVo.class);
                            infoList.forEach(i -> {
                                i.setColName("data." + i.getColName());
                            });
                            resultList.addAll(infoList);
                        } else {
                            System.out.println("返回参数 split.length == 2 找不到的对象: " + resultName);
                        }
                    }
                }

                if (split.length == 3) {
                    String s1 = split[1].replace("»", "");
                    if (s1.equals("IPage")) {
                        resultList.addAll(colMap.get("IPage"));
                    }

                    String s2 = split[2].replace("»", "");
                    List<ColInfoVo> infoList = colMap.get(s2);
                    if (CollectionUtil.isNotEmpty(infoList)) {
                        // 利用序列化技术, 实现 深拷贝
                        List<ColInfoVo> newList = JSON.parseArray(JSON.toJSONString(infoList), ColInfoVo.class);
                        newList.forEach(i -> {
                            if (s1.equals("IPage")) {
                                i.setColName("data.records." + i.getColName());
                            } else {
                                i.setColName("data." + i.getColName());
                            }
                        });
                        resultList.addAll(newList);
                    } else {
                        System.out.println("返回参数 split.length == 3 找不到的对象: " + resultName);
                    }
                }
            } else {
                System.out.println("返回参数 没有R的情况: " + resultName);
            }


            if (CollectionUtil.isNotEmpty(resultList) && resultList.size() > 0) {
                resultList.forEach(p -> {
                    mdStr.append("|" + p.getColName() + "|" + p.getType() + "|" + p.getDescription() + "|\n");
                });
                mdStr.append("\n\n");

                mdStr.append("**返回示例:** \n\n");
                mdStr.append("~~~json\n");
                String shiLi = SwaggerResultListToShiLiJson.getShiLi(resultList);
                mdStr.append(SwaggerResultListToShiLiJson.geshihua(shiLi) + "\n");
                mdStr.append("~~~\n");
            }


        }
        return mdStr;
    }


    /**
     * 解析swagger.json文件中的接口信息
     *
     * @param swaggerObj
     * @return
     * @throws IOException
     */
    public static List<SwaggerVo> getSwaggerVoList(JSONObject swaggerObj, Map<String, List<ColInfoVo>> colMap) {

        JSONObject pathList = swaggerObj.getJSONObject("paths");
        // 所有接口
        Set<String> pathsKeySet = pathList.keySet();
        List<SwaggerVo> newList = new ArrayList<>();
        for (String pathName : pathsKeySet) {
            SwaggerVo vo = new SwaggerVo();
            // 接口地址
            vo.setPath(pathName);

            // 单个接口的内容
            JSONObject pathObject = pathList.getJSONObject(pathName);
            for (String method : pathObject.keySet()) {
                // 请求方式
                vo.setMethod(method);
                JSONObject methodObj = pathObject.getJSONObject(method);
                if (methodObj != null) {
                    // 业务场景
                    JSONArray scene = methodObj.getJSONArray("tags");
                    vo.setScene(scene.getString(0));
                    // 接口描述
                    vo.setDescription(methodObj.getString("summary"));


                    // TODO 请求参数
                    JSONArray parameters = methodObj.getJSONArray("parameters");
                    if (parameters != null) {
                        List<ColInfoVo> paramList = new ArrayList<>();

                        for (int i = 0; i < parameters.size(); i++) {
                            JSONObject object = parameters.getJSONObject(i);

                            JSONObject schema = object.getJSONObject("schema");
                            // 对象方式传参
                            if (schema != null) {
                                // 对象参数的名称
                                String originalRef = schema.getString("originalRef");
                                if (originalRef != null) {
                                    vo.setParamName(originalRef);
                                } else {
                                    if (object.getString("name").equals("file")) {
                                        paramList.add(new ColInfoVo("file", "file", "文件"));
                                    }
                                    vo.setParamName("file");
                                }
                            }
                            // 普通参数
                            else {
                                paramList.add(new ColInfoVo(object.getString("name"), object.getString("type"), object.getString("description")));
                            }
                        }
                        vo.setParamList(paramList);
                    }

                    // TODO 返回参数
                    JSONObject responses = methodObj.getJSONObject("responses");
                    JSONObject r200 = responses.getJSONObject("200");
                    // 对象方式传参
                    JSONObject schema = r200.getJSONObject("schema");
                    List<ColInfoVo> resultList = new ArrayList<>();

                    if (schema != null) {
                        // 对象参数的名称
                        String originalRef = schema.getString("originalRef");
                        if (StringUtils.isNotEmpty(originalRef)) {
                            vo.setResultName(originalRef);
                        } else {
                            System.out.println("没有originalRef: " + pathName);
                            System.out.println("没有originalRef: " + schema);
                        }
                    }
                    vo.setResultList(resultList);
                }
                newList.add(vo);
            }
        }
        return newList;
    }


    /**
     * 获取所有对象字段信息
     *
     * @param swaggerObj
     * @return
     */
    public static Map<String, List<ColInfoVo>> colMap(JSONObject swaggerObj) {
        Map<String, List<ColInfoVo>> colMap = new HashMap<>();

        List<ColInfoVo> R = new ArrayList<>();
        R.add(new ColInfoVo("code", "integer", "状态码 200-操作成功,其他失败"));
        R.add(new ColInfoVo("msg", "String", "反馈说明"));
        R.add(new ColInfoVo("data", "Object", "数据"));
        colMap.put("R", R);


        List<ColInfoVo> IPage = new ArrayList<>();
        IPage.add(new ColInfoVo("data.current", "integer", "当前页码"));
        IPage.add(new ColInfoVo("data.records", "array", "结果集"));
        IPage.add(new ColInfoVo("data.size", "integer", "每页最大记录数"));
        IPage.add(new ColInfoVo("data.total", "integer", "总数"));
        colMap.put("IPage", IPage);

        // 所有对象
        JSONObject definitions = swaggerObj.getJSONObject("definitions");
        for (String d : definitions.keySet()) {
            if (d.contains("R«")) {
                continue;
            }
            if (d.contains("IPage«")) {
                continue;
            }
            if (d.equals("R")) {
                continue;
            }
            // 单个对象
            JSONObject dObj = definitions.getJSONObject(d);
            // 所有字段
            JSONObject properties = dObj.getJSONObject("properties");

            List<ColInfoVo> colList = new ArrayList<>();
            for (String p : properties.keySet()) {
                JSONObject colObj = properties.getJSONObject(p);
                ColInfoVo info = new ColInfoVo(p, colObj.getString("type"), colObj.getString("description"));
                colList.add(info);
            }
            colMap.put(d, colList);
        }
        return colMap;
    }

    /**
     * 读取 resources 目录下的文件中的内容
     *
     * @param fileName
     * @return
     * @throws IOException
     */
    public JSONObject readFileFromClasspath(String fileName) throws IOException {
        ClassLoader classLoader = getClass().getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream(fileName);
        if (inputStream == null) {
            throw new IllegalArgumentException("File not found! " + fileName);
        }
        StringBuilder contentBuilder = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) {
            String currentLine;
            while ((currentLine = br.readLine()) != null) {
                contentBuilder.append(currentLine).append("\n");
            }
        }
        JSONObject parse = JSONObject.parse(contentBuilder.toString());

        return parse;
    }

}
